package com.common.service.impl;

import java.util.Calendar;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import com.common.redis.RedisUtil;
import org.apache.log4j.Logger;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.ExcessiveAttemptsException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import com.common.dao.AccountInfoDAO;
import com.common.dao.LogUserFailDAO;
import com.common.dao.PersonInfoDAO;
import com.common.dao.PrivilegeInfoDAO;
import com.common.dto.AccountInfoDTO;
import com.common.dto.LogUserFailDTO;
import com.common.dto.PersonInfoDTO;
import com.common.dto.PrivilegeDTO;
import com.common.service.AccountInfoService;
import com.common.service.base.BaseService;
import com.common.util.ChangePassword;
import com.common.util.ConstantDefine;
import com.common.util.DateUtil;
import com.common.util.GetIPUtil;
import com.common.util.GetMacAddress;
import com.common.util.ShiroUtil;
import com.common.util.StringUtil;
import com.github.pagehelper.PageInfo;

/**
 *
 */
@Service
public class AccountInfoServiceImpl extends BaseService<AccountInfoDTO> implements AccountInfoService{

    protected Logger logger = Logger.getLogger(getClass().getName());

	@Autowired
	private AccountInfoDAO accountInfoDAO;

	@Autowired
	private PersonInfoDAO personInfoDAO;

	@Autowired
	private PrivilegeInfoDAO privilegeInfoDAO;

	@Autowired
	private LogUserFailDAO logUserFailDAO;

	@Autowired
	private RedisUtil redisUtil;

	@Value("${accountKey}")
	private String accountKey;

   


	/**
	 * 内部账号（客户、管理员、配送员）和密码验证
	 * 	--存在，但未注册过
	 * @author wuronglai
	 * @param entity	accountCode,accountPwd
	 * @return
	 */
	@Override
	public Map<String, Object> check(AccountInfoDTO entity) {

		return null;
	}

	@Override
	public Map<String, Object> init() {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public AccountInfoDTO getAccountInfo(AccountInfoDTO account) {
		AccountInfoDTO accountDTO  = accountInfoDAO.getAccountInfo(account);
		if (null != accountDTO) {
			account.setId(accountDTO.getId());
			return accountDTO;
		}
		return null;
	}

	

	@Override
	public List<PrivilegeDTO> findPrivilegesByPersonCode(String personCode) {
		return personInfoDAO.findPrivilegesByPersonCode(personCode);
	}

	@Override
	public AccountInfoDTO selectByDTO(AccountInfoDTO accountInfo) {
		return accountInfoDAO.selectByDTO(accountInfo);
	}

    
    /**
     * 管理员修改用户密码
     * Created by wrl on 2017/07/22
     * @param entity 入参id为personInfo的id
     * @return
     */
    @Override
    public Map<String, Object> changePwd(AccountInfoDTO entity) {
        Map<String, Object> map = new HashMap<>();
        map.put(ConstantDefine.FLAG,false);
        String oldPwd = entity.getOldPwd();
        String newPwd = entity.getAccountPwd();
        if(null == oldPwd || "".equals(oldPwd)){
            map.put(ConstantDefine.CHECK_ERR_MSG,"密码为空");
            return map;
        }
        PersonInfoDTO personInfoDTO = personInfoDAO.selectByPrimaryKey(entity.getId());
        entity = accountInfoDAO.selectByPersonCode(personInfoDTO.getPersonCode());
        boolean flag = checkAccountPwd(entity,oldPwd);
        if(!flag){
            map.put(ConstantDefine.CHECK_ERR_MSG,"原密码错误");
            return map;
        }
        entity.setAccountPwd(newPwd);
        entity = encryptAccountPwd(entity);
        accountInfoDAO.updateByPrimaryKeySelective(entity);
		redisUtil.del("shiro_redis_session:"+entity.getAccountCode());
        map.put(ConstantDefine.FLAG,true);
        return map;
    }

    private boolean checkAccountPwd(AccountInfoDTO entity,String oldPwd) {
        entity = decryptAccountPwd(entity);
        if(oldPwd.equals(entity.getAccountPwd())){
			return true;
		}
        else{
			return false;
		}
    }

    /**
     * 加密
     * @author wuronglai
     * @param accountInfo
     * @return
     */
	@Override
    public AccountInfoDTO encryptAccountPwd(AccountInfoDTO accountInfo){
        AccountInfoDTO temp = new AccountInfoDTO();
        if(accountInfo.getId() == null && accountInfo.getPersonCode() != null){
            temp.setPersonCode(accountInfo.getPersonCode());
            temp.setStatus(null);
            temp = accountInfoDAO.selectByDTO(temp);
            accountInfo.setId(temp.getId());
        }else{
            temp = accountInfo;
        }
        String afterPassword = ChangePassword.changePasswd(temp.getId(), accountInfo.getAccountPwd(), accountKey);
        accountInfo.setAccountPwd(afterPassword);
        return accountInfo;
    }

    /**
	 * 解密
	 * @author wuronglai
	 * @param accountInfo
	 * @return
	 */
	@Override
	public AccountInfoDTO decryptAccountPwd(AccountInfoDTO accountInfo){
		String decryptPassword = ChangePassword.decryptPasswd(accountInfo.getId(), accountInfo.getAccountPwd(), accountKey);
		accountInfo.setAccountPwd(decryptPassword);
		return accountInfo;
	}


	@Override
	public Map<String,Object> login(AccountInfoDTO account,HttpServletRequest request) {

		//得到输入的用户名及密码,是否记住我
		String accountCode = account.getAccountCode();
		String accountPwd = account.getAccountPwd();
 		Boolean rememberMe = account.isRememberMe();

		//创建返回结果集result
		Map<String,Object> result = new HashMap<String,Object>();
		//输入框错误
		Map<String,Object> fieldErrMsg = new HashMap<String,Object>();

		//判断用户名和密码是否为空，为空返回登陆页面，提示用户输入账号和密码
		if (StringUtil.isBlank(accountCode)) {
			//添加提示信息，返回登陆页面
			fieldErrMsg.put("accountCode", "请填写账号");
		}
		if (StringUtil.isEmpty(accountPwd)) {
			fieldErrMsg.put("accountPwd", "请填写密码");
		}
		if(!fieldErrMsg.isEmpty()){
			result.put(ConstantDefine.FLAG, false);
			result.put(ConstantDefine.FIELD_ERR_MSG, fieldErrMsg);
			return result;
		}

		//得到一个基于用户数据的 Subject
		Subject subject = SecurityUtils.getSubject();
		//得到token，到shiro中去认证
		UsernamePasswordToken token = new UsernamePasswordToken(accountCode,accountPwd,rememberMe);
		try {
			//验证用户、密码
			subject.login(token);
			logger.info("验证通过，成功登录！");
			result.put(ConstantDefine.FLAG, true);
			result.put(ConstantDefine.CHECK_ERR_MSG, "登录成功！");
		} catch (ExcessiveAttemptsException e) {
			// 记录账号登录失败次数
			result.put(ConstantDefine.FLAG, false);
			result.put(ConstantDefine.CHECK_ERR_MSG, e.getMessage());
			return result;
		} catch (AuthenticationException e) {
			logger.info("登录其他异常:",e);
			result.put(ConstantDefine.FLAG, false);
			String error = "locked".equals(e.getMessage())?"账号被锁定，请联系管理员":"账号或者密码错误";
			result.put(ConstantDefine.CHECK_ERR_MSG, error);
			return result;
		}

		//将数据库原有的账号信息返回给account实体，方便后面获取真实的personCode
		//根据account查找到account实体(查找前account中的accountCode值可能是手机号，邮箱，账号，查找后accountCode就是账号)
		account = getAccountInfo(account);
		//得到personCode
		String personCode = account.getPersonCode();

		//得到账号：accountCode
		accountCode = account.getAccountCode();
		//得到account中的id(修改个人密码时要用)
		String accountId = account.getId();
		//将account的信息放到session中
		//id
		ShiroUtil.setSession(ConstantDefine.ACCOUNT_ID_SESSION, accountId);
		//personCode
		ShiroUtil.setSession(ConstantDefine.PERSONCODE_SESSION, personCode);
		//accountCode
		ShiroUtil.setSession(ConstantDefine.ACCOUNT_CODE_SESSION, accountCode);
		//account
		ShiroUtil.setSession(ConstantDefine.ACCOUNTINFO_SESSION, account);

		//得到一个完整信息的Person实体类
        PersonInfoDTO personInfo = personInfoDAO.selectByPersonCode(personCode);
        //person
        ShiroUtil.setSession("personInfo", personInfo);

		//请求的IP
		final String ipAddr = GetIPUtil.getIpAddr(request);
		ShiroUtil.setSession("ipAddr", ipAddr);
		//登录时间
		String loginDate = DateUtil.getSystemTimeStr();
		ShiroUtil.setSession("loginDate", loginDate);
		//开启线程  加快获取mac地址速度
		new Thread(){
			@Override
			public void run() {
				String macAddress = GetMacAddress.getMacAddress(ipAddr);
				ShiroUtil.setSession("macAddress", macAddress);
			};
		}.start();
		//person-真实名称
		if(null != personInfo.getRealName()){
			ShiroUtil.setSession(ConstantDefine.REAL_NAME_SESSION, personInfo.getRealName());
		}
		//person-角色type
		ShiroUtil.setSession(ConstantDefine.PERSON_TYPE_SESSION, account.getType());

		setUserType(account.getType(),result);
		//类型转换
		/*if("0".equals(account.getType())){
			return "forward:backManagement";
		}*/

		return result;
	}

	private void setUserType(String type,Map<String, Object> result){

		// 0 —>管理员
		if ("0".equals(type)) {
			result.put("userType", "manager");
            result.put("page","indexAdmin.html");
		} else if ("1".equals(type)) {
            //1 —> 客户
            result.put("userType", "customer");
            result.put("page","indexClient.html");
        } else if ("2".equals(type)) {
            //2 —> 配送员
            result.put("userType", "delivery");
            result.put("page","indexCourier.html");
        }
	}

	@Override
	public PageInfo<AccountInfoDTO> selectCustomPaging(AccountInfoDTO entity) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public Map<String, Object> checkUpdate(AccountInfoDTO entity) {
		// TODO Auto-generated method stub
		return null;
	}

    /**
     * 获取权限列表
     * @param personCode
     * @return
     */
    @Override
    public List<String> selectAuthorityList(String personCode) {
        List<String> list = accountInfoDAO.selectAuthorityList(personCode);
        return list;
    }

	@Override
    public void unlock(String lockedUser,String loginUser){
    	LogUserFailDTO logUserFailDTO = new LogUserFailDTO();
		logUserFailDTO.setCreator(lockedUser);
		logUserFailDTO.setStatus("1");
		// 获取锁定账户登录尝试的次数
		logUserFailDTO = logUserFailDAO.selectOne(logUserFailDTO);
		if (logUserFailDTO!=null) {
			logUserFailDTO.setStatus("0");
			logUserFailDTO.setModifier(loginUser);
			logUserFailDTO.setModifyTime(Calendar.getInstance().getTime());
			//删除锁定信息
			logUserFailDAO.updateByPrimaryKey(logUserFailDTO);
		}
    }
}
